package com.atguigu.gulimall.finance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.finance.dao.MainDao;
import com.atguigu.gulimall.finance.entity.MainEntity;
import com.atguigu.gulimall.finance.entity.TypeEntity;
import com.atguigu.gulimall.finance.entity.vo.ExcelFinanceVo;
import com.atguigu.gulimall.finance.entity.vo.FinanceVo;
import com.atguigu.gulimall.finance.entity.vo.MainEntityVo;
import com.atguigu.gulimall.finance.entity.vo.MainPipDataVo;
import com.atguigu.gulimall.finance.service.MainService;
import com.atguigu.gulimall.finance.service.TypeService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


@Service("incomeService")
public class MainServiceImpl extends ServiceImpl<MainDao, MainEntity> implements MainService {
    final
    TypeService typeService;

    public MainServiceImpl(TypeService typeService) {
        this.typeService = typeService;
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        AtomicReference<String> type = new AtomicReference<>("支出");
        QueryWrapper<MainEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if (StrUtil.isNotEmpty(key)) {
            wrapper.and(w -> w.eq("id", key).or().like("income_name", key));
        }
        IPage<MainEntity> page = this.page(
                new Query<MainEntity>().getPage(params),
                wrapper
        );
        List<MainEntityVo> collect = page.getRecords().stream().map(item -> {
            MainEntityVo mainEntityVo = new MainEntityVo();
            BeanUtil.copyProperties(item, mainEntityVo);
            if (item.getIncomeType() == 0) {
                type.set("收入");
            } else {
                type.set("支出");
            }
            mainEntityVo.setIncomeTypeStr(String.valueOf(type));
            return mainEntityVo;
        }).collect(Collectors.toList());
        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(collect);
        return pageUtils;
    }

    @Cacheable(value = {"incomeSumMoney"}, key = "#root.methodName", sync = true)
    @Override
    public BigDecimal getSumMoney(String typeName, Integer incomeType) {
        return this.baseMapper.getSumMoney(typeName, incomeType);
    }

    @Cacheable(value = {"incomeSumMoney"}, key = "#root.methodName", sync = true)
    @Override
    public List<MainPipDataVo> getExpendSumMoney() {
        List<TypeEntity> list = typeService.list();
        if (list != null) {
            if (list.size() > 0) {
                return list.stream().map(item -> {
                    MainPipDataVo mainPipDataVo = new MainPipDataVo();
                    BigDecimal incomeMoneySum = getSumMoney(item.getTypeName(), 1);
                    if (incomeMoneySum != null) {
                        mainPipDataVo.setValue(incomeMoneySum);
                        mainPipDataVo.setName(item.getTypeName());
                    }
                    return mainPipDataVo;
                }).collect(Collectors.toList());
            }
        }
        return null;
    }

    @Transactional
    @CacheEvict(value = {"incomeSumMoney"}, allEntries = true)
    @Override
    public void saveMain(MainEntity income) {
        income.setCreateTime(new Date());
        income.setUpdateTime(new Date());
        this.save(income);
    }

    @Transactional
    @CacheEvict(value = {"incomeSumMoney"}, allEntries = true)
    @Override
    public void updateIcomeById(MainEntity income) {
        income.setUpdateTime(new Date());
        this.updateById(income);
    }

    @Transactional
    @CacheEvict(value = {"incomeSumMoney"}, allEntries = true)
    @Override
    public void removeIcomeByIds(List<Long> asList) {
        this.removeByIds(asList);
    }

    @Override
    public MainEntityVo getInfo(Long id) {
        MainEntity income = this.getById(id);
        MainEntityVo mainEntityVo = new MainEntityVo();
        BeanUtil.copyProperties(income, mainEntityVo);
        mainEntityVo.setIncomeTypeValue(income.getIncomeType().toString());
        return mainEntityVo;
    }

    @Cacheable(value = {"incomeSumMoney"}, key = "#root.methodName", sync = true)
    @Override
    public FinanceVo getSumFinance() {
        FinanceVo financeVo = new FinanceVo();
        //1.获取总支出
        QueryWrapper<MainEntity> wrapper = new QueryWrapper<>();
        // where income_type=1
        wrapper.select("sum(income_money) as totalExp").eq("income_type", 1);
        MainEntity entity = this.getOne(wrapper);
        if (entity == null) {
            financeVo.setTotalExp(new BigDecimal("0.00"));
        } else {
            financeVo.setTotalExp(entity.getTotalExp());
        }
        return getFinanceByInc(financeVo);
    }

    private FinanceVo getFinanceByInc(FinanceVo financeVo) {
        QueryWrapper<MainEntity> wrapper = new QueryWrapper<>();
        wrapper.select("sum(income_money) as totalInc").eq("income_type", 0);
        MainEntity entity = this.getOne(wrapper);
        if (entity == null) {
            financeVo.setTotalInc(new BigDecimal("0.00"));
        } else {
            financeVo.setTotalInc(entity.getTotalInc());
        }
        return financeVo;
    }

    @Cacheable(value = {"incomeSumMoney"}, key = "#root.methodName", sync = true)
    @Override
    public List<ExcelFinanceVo> getAllFinalce() {
        List<MainEntity> list = this.list();
        return list.stream().map(item -> {
            ExcelFinanceVo vos = new ExcelFinanceVo();
            BeanUtil.copyProperties(item, vos);
            if (item.getIncomeType() == 1) {
                vos.setIncomeTypeName("支出");
            } else {
                vos.setIncomeTypeName("收入");
            }
            return vos;
        }).collect(Collectors.toList());
    }

    @Cacheable(value = {"incomeSumMoney"}, key = "#root.methodName", sync = true)
    @Override
    public List<MainPipDataVo> getSumMoneyIcome() {
        List<TypeEntity> list = typeService.list();
        if (list != null) {
            if (list.size() > 0) {
                return list.stream().map(item -> {
                    MainPipDataVo mainPipDataVo = new MainPipDataVo();
                    BigDecimal incomeMoneySum = getSumMoney(item.getTypeName(), 0);
                    if (incomeMoneySum != null) {
                        mainPipDataVo.setValue(incomeMoneySum);
                        mainPipDataVo.setName(item.getTypeName());
                    }
                    return mainPipDataVo;
                }).filter(i -> i.getName() != null && i.getValue() != null).collect(Collectors.toList());
            }
        }
        return null;
    }

}